-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable mode-specific transfers by storing mode information in transfers #6293
Enable mode-specific transfers by storing mode information in transfers #6293
Conversation
The tests will fail for |
Interestingly |
Interestingly now after making changes not related to functionality, the |
…into split-transfers-by-mode-pathtransfer-mode
…er requests for WALK mode.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dev-2.x #6293 +/- ##
=============================================
+ Coverage 69.79% 69.82% +0.03%
- Complexity 17788 17842 +54
=============================================
Files 2017 2022 +5
Lines 76042 76303 +261
Branches 7781 7804 +23
=============================================
+ Hits 53074 53281 +207
- Misses 20264 20306 +42
- Partials 2704 2716 +12 ☔ View full report in Codecov by Sentry. |
if (pathTransfer == null) { | ||
EnumSet<StreetMode> modes = EnumSet.of(mode); | ||
distinctTransfers.put( | ||
transferKey, | ||
new PathTransfer(stop, sd.stop, sd.distance, sd.edges, modes) | ||
); | ||
} else { | ||
pathTransfer.addMode(mode); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could add a comment here to explain what these different cases mean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added comments for the different cases
} | ||
// Calculate flex transfers if flex routing is enabled. | ||
for (RouteRequest transferProfile : flexTransferRequests) { | ||
StreetMode mode = transferProfile.journey().transfer().mode(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this just always WALK?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have always assumed that flex transfers can only be on foot. I think this is reasonable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this to StreetMode mode = StreetMode.WALK;
@@ -250,6 +250,61 @@ public void testMultipleRequestsWithPatterns() { | |||
); | |||
} | |||
|
|||
@Test | |||
public void testPathTransfersWithModesForMultipleRequestsWithPatterns() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does multiple requests with patterns mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to follow a similar naming convention as the other tests in the file. With patterns means that trippatterns are added to the timetablerepository of the test. Multiple requests means that transfers are generated for multiple requests that have different modes:
var reqWalk = new RouteRequest();
reqWalk.journey().transfer().setMode(StreetMode.WALK);
var reqBike = new RouteRequest();
reqBike.journey().transfer().setMode(StreetMode.BIKE);
var transferRequests = List.of(reqWalk, reqBike);
this.toStop = toStop; | ||
this.edges = edges; | ||
this.distanceMeters = (int) edges.stream().mapToDouble(Edge::getDistanceMeters).sum(); | ||
this.modes = modes; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably want to make this immutable. EnumSet are not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the getModes
method to clone the enum set
var walkTransfers = timetableRepository | ||
.getAllPathTransfers() | ||
.stream() | ||
.filter(pathTransfer -> pathTransfer.getModes().contains(StreetMode.WALK)) | ||
.toList(); | ||
var bikeTransfers = timetableRepository | ||
.getAllPathTransfers() | ||
.stream() | ||
.filter(pathTransfer -> pathTransfer.getModes().contains(StreetMode.BIKE)) | ||
.toList(); | ||
var carTransfers = timetableRepository | ||
.getAllPathTransfers() | ||
.stream() | ||
.filter(pathTransfer -> pathTransfer.getModes().contains(StreetMode.CAR)) | ||
.toList(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please extract a method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created a getTransfersByMode
method in TimetableRepository
Does this mean that this PR allows you to compute CAR transfers between stops that don't serve cars at all? |
@@ -41,6 +43,7 @@ public static RaptorTransferIndex create( | |||
var transfers = transfersByStopIndex | |||
.get(fromStop) | |||
.stream() | |||
.filter(transfer -> transfer.getModes().contains(mode)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is run only once and then cached for the specific combination of request parameters, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is run once for each cache request. You can see the code that uses this in RaptorRequestTransferCache
return this.modes; | ||
} | ||
|
||
public boolean addMode(StreetMode mode) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we want to make this class mutable. Can you create a copy method, for example withAddedMode
that returns a new instance instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this to use the withAddedMode
method
@@ -46,6 +56,14 @@ public List<Edge> getEdges() { | |||
return this.edges; | |||
} | |||
|
|||
public EnumSet<StreetMode> getModes() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't want to expose the mutable EnumSet. Can you replace it with a method like allows(CAR)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the getModes
method to clone the enum set
.map(transferProfile -> transferProfile.journey().transfer().mode()) | ||
.collect(Collectors.toSet())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.map(transferProfile -> transferProfile.journey().transfer().mode()) | |
.collect(Collectors.toSet())) { | |
.map(transferProfile -> transferProfile.journey().transfer().mode()) | |
.distinct() | |
.toList() |
Not a huge deal but avoiding a set gives you predictable sort order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this is a good suggestion. I changed it to this
Yes, in a future PR (#6215) I will implement more configurability for transfers |
} | ||
|
||
public EnumSet<StreetMode> getModes() { | ||
return modes.clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return modes.clone(); | |
return EnumSet.copyOf(modes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this
this.toStop = toStopIndex; | ||
this.distanceMeters = distanceMeters; | ||
this.edges = null; | ||
this.modes = modes; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This transfer is not serialized. Here you can use Sets.immutableEnumSet and then never have to worry about cloning or copying.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this to use Sets.immutableEnumSet
for (StreetMode mode : transferRequests | ||
.stream() | ||
.map(transferProfile -> transferProfile.journey().transfer().mode()) | ||
.distinct() | ||
.toList()) { | ||
LOG.info( | ||
"Created {} transfers for mode {}.", | ||
transfersByStop | ||
.values() | ||
.stream() | ||
.filter(pathTransfer -> pathTransfer.getModes().contains(mode)) | ||
.count(), | ||
mode | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is quite difficult to read. I would probably continue the stream instead of making it a list and then looping over it, and then call some method with the mode as an argument that does the logging. So something like:
transferRequests
.stream()
.map(transferProfile -> transferProfile.journey().transfer().mode())
.distinct()
.peek(mode -> logTransfersForMode(mode));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it to this:
transferRequests
.stream()
.map(transferProfile -> transferProfile.journey().transfer().mode())
.distinct()
.forEach(mode ->
LOG.info(
"Created {} transfers for mode {}.",
timetableRepository.getTransfersByMode(mode).size(),
mode
)
);
I am following this as I am now testing BICYCLE routing on our deployment. The current deployment configuration only has "walk" with However, if I set the |
@@ -434,7 +435,7 @@ public Collection<PathTransfer> getTransfersByStop(StopLocation stop) { | |||
return transfersByStop.get(stop); | |||
} | |||
|
|||
public Collection<PathTransfer> getTransfersByMode(StreetMode mode) { | |||
public List<PathTransfer> getTransfersByMode(StreetMode mode) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this method should be called findTransfers
according to the naming conventions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I renamed getTransfersByMode
to findTransfers
@t2gran can we run the speed tests against that? Do you know how to do it? |
@@ -31,16 +35,20 @@ public class Transfer { | |||
|
|||
private final List<Edge> edges; | |||
|
|||
public Transfer(int toStop, List<Edge> edges) { | |||
private final ImmutableSet<StreetMode> modes; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know there was a lot of back and forth with this. In the end @t2gran says he didn't want Guava collection, so lets use Collections.unmodifiableSet.
private final ImmutableSet<StreetMode> modes; | |
private final Set<StreetMode> modes; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason we can do it here is that it's not serialized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it to this
this.toStop = toStop; | ||
this.edges = edges; | ||
this.distanceMeters = (int) edges.stream().mapToDouble(Edge::getDistanceMeters).sum(); | ||
this.modes = Sets.immutableEnumSet(modes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.modes = Sets.immutableEnumSet(modes); | |
this.modes = Collections.unmodifiableSet(modes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it to this
this.toStop = toStopIndex; | ||
this.distanceMeters = distanceMeters; | ||
this.edges = null; | ||
this.modes = Sets.immutableEnumSet(modes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.modes = Sets.immutableEnumSet(modes); | |
this.modes = Collections.unmodifiableSet(modes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it to this
@@ -68,6 +76,10 @@ public List<Edge> getEdges() { | |||
return edges; | |||
} | |||
|
|||
public ImmutableSet<StreetMode> getModes() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't actually need to expose the collection at all. Simply add a method allowsMode(mode)
. So you don't even have to think about if it's mutable or immutable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also document the method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed getModes
to allowsMode
@@ -433,6 +435,14 @@ public Collection<PathTransfer> getTransfersByStop(StopLocation stop) { | |||
return transfersByStop.get(stop); | |||
} | |||
|
|||
public List<PathTransfer> findTransfers(StreetMode mode) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add Javadoc here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added
/** | ||
* Maps street mode to transfer traverse mode. | ||
*/ | ||
public class StreetModeToTransferTraverseModeMapper { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice that you extraced the mapper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
I also ran the speed test on this branch and I cannot see any changes: https://tinyurl.com/27zv22uz Performance-wise this is fine. |
return EnumSet.copyOf(modes); | ||
} | ||
|
||
public PathTransfer withAddedMode(StreetMode mode) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Javadoc please.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added
@@ -68,6 +75,10 @@ public List<Edge> getEdges() { | |||
return edges; | |||
} | |||
|
|||
public boolean allowsMode(StreetMode mode) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Javadoc here and then we are good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll fix this next week. Btw does this need the bump serialization id
label?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. You are storing a new field into the graph.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This now has a comment
Summary
This PR adds
StreetMode
information to transfers. This enables using mode-specific transfers during runtime.Notes:
PathTransfer
s with mode information, this could also be done by using mappings from modes to transfers.Issue
Resolves a TODO comment about adding
StreetMode
information in thePathTransfer
class.Related to #5875
Unit tests
Added a new test to
DirectTransferGeneratorTest
.Documentation
No documentation has been added.
Bumping the serialization version id
This changes how transfers are generated during the graph build.